/****************************************************************************

	COPYRIGHT(C) MAXSI SOFTWARE, JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010

    This file is part of Maxsi RXP.

    Maxsi RXP is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maxsi RXP is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Maxsi RXP. If not, see <http://www.gnu.org/licenses/>.

	*/ #include "MaxsiRXPContributors.h" /*

	If you modify this file, please enter your name below and provide contact
	information in MaxsiRXPContributors.h. For more information please see
	MaxsiRXPContributors.h.
	
	Contributors to this file:

	- Jonas 'Sortie' Termansen
	- [your name here]


	MaxsiRXP.exe
	A system to control MaxsiRXP Systems.

	RXPIO.cpp
	Low-level IO code for MaxsiRXP

****************************************************************************/

#include "MaxsiEngine.h"
#include "Mswsock.h"

//=============================================================================
//	ME_Thinker defines
//=============================================================================
#define ME_THINK_PRECISION_NORMAL	32
#define ME_THINK_PRECISION_INSTANT	0
#define ME_THINK_PRECISION_LOW		100
#define ME_THINK_NEVER				0xFFFFFFFF
#define ME_THINK_SUCCESS			0
#define	ME_THINK_FAIL				1

//=============================================================================
//	RXP-specific defines
//=============================================================================
#define RXP_WINSOCK_REQUIRED_MAJOR	2
#define RXP_WINSOCK_REQUIRED_MINOR	0

#define RXP_UNCONNECTED				0
#define RXP_ACCEPTING				1
#define RXP_CONNECTING				2
#define RXP_CONNECTED				3
#define	RXP_INPUT					0
#define	RXP_OUTPUT					1

#define RXP_LISTEN_SUCCESS			0
#define RXP_LISTEN_AGAIN			1
#define RXP_LISTEN_HANDLING_ERROR	2
#define RXP_LISTEN_FAIL				3

#define RXP_LISTEN_DONT				0
#define	RXP_LISTEN_SHOULD			1
#define	RXP_LISTEN_LISTENING		2

#define RXP_CONCURRENT_LISTENS		1 // This should be one. There is no need for multiple listens when doing this async.

#define	RXP_HANDLER_SUCCESS			0
#define RXP_HANDLER_FAILURE			1

#define RXP_ERROR_ALLOC_FAIL		0xFFFFFFFF

//=============================================================================
//	Forward declarations
//=============================================================================
class	ME_Thinker_Queue;
class	ME_Thinker;
class	RXPPeer;
class	RXPPeerHandler;
class	RXPPeerHandlerReliable;
class	RXPConnection;
struct	RXPOVERLAPPED;

//=============================================================================
//	ME_Thinker_Queue: A class that handles timer queues
//=============================================================================
class ME_Thinker_Queue
{
public:
	ME_Thinker_Queue();
	~ME_Thinker_Queue();

public:
	HANDLE	TimerQueue;

};

//=============================================================================
//	ME_Thinker: A class that causes a callback after a specific amount of time
//=============================================================================
class ME_Thinker
{
public:
	ME_Thinker();
	~ME_Thinker();

public:
	virtual	int			Think();
	virtual	int			OnThink();
	virtual	int			RequestThinkBefore(DWORD Miliseconds, DWORD Precision = ME_THINK_PRECISION_NORMAL);

public:
	CRITICAL_SECTION	MayExecThinkFunction; // Thread Safety.
	DWORD				NextScheduledTime;
	DWORD				NextRequestedTime;
	HANDLE				Timer;

};

//=============================================================================
//	RXPOVERLAPPED: An extension to the default OVERLAPPED struct
//=============================================================================
struct RXPOVERLAPPED : public OVERLAPPED
{
	RXPPeer*			Peer;
	RXPConnection*		Connection;
	int					BufferType; // ME_BUFFER_TYPE_*

};

//=============================================================================
//	RXPPeerHandler: An error-handling interface to the RXPPeer class
//=============================================================================
class RXPPeerHandler
{
public:
	virtual	int			ListenHandleError(int Error, char* Parameter = NULL);
	virtual	int			ConnectHandleError(int Error, char* Parameter = NULL);

public:
	RXPPeer*			Peer;

};

//=============================================================================
//	RXPPeerHandlerReliable: Handles RXPPeer errors gracefully and keeps trying
//=============================================================================
class RXPPeerHandlerReliable : public RXPPeerHandler
{
public:
	virtual	int			ListenHandleError(int Error, char* Parameter = NULL);
	virtual	int			ConnectHandleError(int Error, char* Parameter = NULL);

};

//=============================================================================
//	RXPPeer: A RXP compatible server giving access to a virtual filesystem
//=============================================================================
class RXPPeer : public ME_Thinker
{
public:
	RXPPeer();
	~RXPPeer();

public:
	virtual	int			OnThink();

public:
	RXPPeerHandler*		Handler;
	bool				SetHandler(RXPPeerHandler* NewHandler);

public:
	BOOL				InitializePeer(HINSTANCE hInstance);
	BOOL				DestroyPeer();

public:
	HWND				PeerHWND;

// Call these instead to use the error handler
public:
	int					Listen(short Port);

public:
	int					DoListen(short Port);
	int					ShutdownListen();

public:
	int					ListeningState;				
	bool				ListenReliably;
	size_t				ListenAttempt;
	DWORD				ListenWait;
	DWORD				ListenNextTime;

public:
	int					RetryListenAfterAdditional(DWORD Miliseconds);
	int					ListenSuccess();
	size_t				GetListenAttempt();

public:
	int					WSAState;
	int					WSALastError;
	WSADATA				WSAData;
	bool				WSAInitialized(); // Returns whether Winsock has been initialized
	bool				WSASupported(); // Returns whether we have the Winsock version required
	bool				WSAError();	// Notes a WSA Error occured

public:
	bool				IsPeerBlackListed(char* Peer);

public:
	RXPConnection**		AcceptingConnection;
	SOCKET				ListenSocket;
	short				ListenPort;

};

bool	RXPPeerClassRegistered		=	false;

//=============================================================================
//	RXPConnection: Manages TCP/IP connections to the local server and the
//	remote RXP Peer on the other end.
//=============================================================================
class RXPConnection : public ME_Thinker
{
public:
	RXPConnection();
	~RXPConnection();

public:	
	CRITICAL_SECTION	MayExecThinkFunction; // Thread Safety.

public:
	RXPPeer*			Peer;
	size_t				ConnectionId;

public:
	bool				WSAError();

public:
	MESTR*				HostName;
	SOCKET				Socket;
	int					Connected;
	short				ListenPort;
	bool				Connector;

public:
	DWORD				LastRemoteActivity;

public:
	bool				DeleteMe_WriteOnce;

public:
	#define				RXP_ADDRBUFFER_LEN (sizeof(sockaddr_in)+16 + sizeof(sockaddr_in)+16)
	char				AddrBuffer[RXP_ADDRBUFFER_LEN];

public:
	void				DoneIO(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, RXPOVERLAPPED* lpOverlapped);

public:
	RXPOVERLAPPED		Input;
	RXPOVERLAPPED		Output;
	ME_Buffer*			IBuffer;
	ME_Buffer*			OBuffer;

public:
	size_t				IBitDepth;
	size_t				OBitDepth;

public:
	bool				CreateBuffers();
	bool				DeleteBuffers();

public:
	bool				Connect(MESTR* Host, short Port);
	int					Listen(short Port);
	bool				Shutdown();

public:
	int					OnConnectionAccepted(bool Sync = false);
	bool				OnConnectee();
	bool				OnConnected();
	virtual	int			OnThink();

public:
	bool				Read(size_t Keep);
	bool				Write(char* Buffer, size_t BufferLen);

};

//=============================================================================
//	ME_Thinker Specific Variables
//=============================================================================
ME_Thinker_Queue	Queue;

//=============================================================================
//	RXP Specific Variables
//=============================================================================
size_t	RXP_OBuffer_Size					=	16384;
size_t	RXP_IBuffer_Size					=	16384;
size_t	RXP_Max_Username_Size				=	256;
size_t	RXP_Max_Password_Size				=	256;
size_t	RXP_Max_ResourcePath_Len			=	2048;
size_t	RXP_Max_Sessions					=	1024;
size_t	RXP_Default_Bit_Depth				=	8;
DWORD	RXP_Inactive_Connection_Timeout		=	100;

//=============================================================================
//	Async callback functions
//=============================================================================
void CALLBACK RXPConnection__DoneIOWSA(DWORD dwErrorCode,
					DWORD dwNumberOfBytesTransferred,
					LPOVERLAPPED lpOverlapped,
					DWORD dwFlags);

void CALLBACK RXPConnection__DoneIO(DWORD dwErrorCode,
					DWORD dwNumberOfBytesTransferred,
					LPOVERLAPPED lpOverlapped);

//=============================================================================
//	Timer callbacks
//=============================================================================
//void CALLBACK RXPTimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired);

//void CALLBACK RXPListenCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired);

void CALLBACK ME_Think_Timer_Callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired);

//=============================================================================
//	Window Procedures
//=============================================================================
LRESULT APIENTRY MaxsiRXPPeerProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

LRESULT APIENTRY MaxsiRXPListenProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

LRESULT APIENTRY MaxsiRXPPeerProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	return DefWindowProc(hWnd, message, wParam, lParam);
}

//=============================================================================
//	ME_Thinker_Queue: A class that handles timer queues
//=============================================================================

ME_Thinker_Queue::ME_Thinker_Queue()
{
	TimerQueue			=	CreateTimerQueue();
}

ME_Thinker_Queue::~ME_Thinker_Queue()
{
	if ( TimerQueue ) { DeleteTimerQueueEx(TimerQueue, NULL); TimerQueue = NULL; }
}

//=============================================================================
//	ME_Thinker: A class that causes a callback after a specific amount of time
//=============================================================================

ME_Thinker::ME_Thinker()
{
	NextScheduledTime		=	ME_THINK_NEVER;
	NextRequestedTime		=	ME_THINK_NEVER;
	Timer					=	NULL;

	if (!InitializeCriticalSectionAndSpinCount(&MayExecThinkFunction, 
		0x80000400) ) 
	{
		ME_UNDEFINED_BEHAVIOR("ME_Thinker::ME_Thinker() couldn't initialize InitializeCriticalSectionAndSpinCount(&MayExecThinkFunction)!");
	}
}

ME_Thinker::~ME_Thinker()
{
	DeleteCriticalSection(&MayExecThinkFunction);
}

int ME_Thinker::Think()
{
	int		Result				=	ME_THINK_SUCCESS;

	EnterCriticalSection(&MayExecThinkFunction);

	NextScheduledTime			=	0xFFFFFFFF;

	// Do the actual thinking in a subclass!
	OnThink();

	// If the think function requested a re-think after some time, and
	// we are not already planning one before that, then do so!
	if ( NextScheduledTime != 0xFFFFFFFF )
	{
		if ( Timer ) { DeleteTimerQueueTimer(Queue.TimerQueue, Timer, NULL); Timer = NULL; }

		DWORD	CurrentTime	=	GetTickCount();
		DWORD	DueTime		=	NextScheduledTime - CurrentTime;
		
		// If the scheduled time to think was in the past, then simply
		// set the next think time next milisecond. This avoids a case
		// where subtracting the unsigned integers causes the next
		// think to be somewhere in the very very distant future.
		if ( NextScheduledTime < CurrentTime ) { DueTime = 1; }

		BOOL	TimerResult	=	CreateTimerQueueTimer(
			&Timer,
			Queue.TimerQueue,
			ME_Think_Timer_Callback,
			this,
			DueTime,
			0,
			WT_EXECUTEINIOTHREAD);

		if ( TimerResult == FALSE ) { Result = ME_THINK_FAIL; }

		NextRequestedTime	=	NextScheduledTime;
	}
				
	LeaveCriticalSection(&MayExecThinkFunction);

	return Result;
}

int ME_Thinker::OnThink()
{
	return ME_THINK_SUCCESS;
}

int ME_Thinker::RequestThinkBefore(DWORD Miliseconds, DWORD Precision)
{
	// Calculate whenever the last acceptable time is that we would think again.
	DWORD	LastAcceptableTime		=	GetTickCount() + Miliseconds + Precision;

	// Check if the next scheduled think time is later than the current last
	// acceptable re-think time calculated above.
	if ( NextRequestedTime > LastAcceptableTime )
	{
		// Yep. We need to re-schedule when we think again.
		NextScheduledTime			=	GetTickCount() + Miliseconds;
		return ME_THINK_SUCCESS;
	}

	// Fail only means we didn't schedule a think because an earlier one was
	// already scheduled.
	return ME_THINK_FAIL;
}

//=============================================================================
//	General purpose functions
//=============================================================================

int DoAwesomeRXPStuff(HINSTANCE hInstance)
{
	RXPPeer*	Peer	=	new	RXPPeer;

	if ( Peer == NULL ) { return 0; }

	if ( Peer->InitializePeer(hInstance) == FALSE )
	{
		delete Peer;
		return 0;
	}

	Peer->SetHandler(new RXPPeerHandlerReliable);

	int	ListenResult	=	Peer->Listen(1337);

	//if ( ListenResult != RXP_LISTEN_SUCCESS && ListenResult != RXP_LISTEN_HANDLING_ERROR )
	//{
	//	__debugbreak();
	//}

	return 1;
}

// Converts a sockaddr to a string
MESTR*	RXPAddressToString(LPSOCKADDR Address, DWORD AddressLength)
{
	DWORD	OutputLength	=	3*4 + 3 + 1 + 5 + 1;

	MESTR*	Output			=	new MESTR[OutputLength];

	if ( Output == NULL ) { return NULL; }

	INT		Result			=	WSAAddressToStringM(Address, AddressLength, NULL, Output, &OutputLength);

	if ( Result == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT )
	{
		// Not enough buffer space! Allocate some more!
		delete[] Output; 
		
		MESTR*	Output		=	new MESTR[OutputLength+1];

		if ( Output == NULL ) { return NULL; }

		Result				=	WSAAddressToStringM(Address, AddressLength, NULL, Output, &OutputLength);

		if ( Result == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT ) { return NULL; }

		return Output;
	}
	else if ( Result != 0 )
	{
		delete[] Output;
		return NULL;
	}

	return Output;
}

//=============================================================================
//	RXPPeerHandler
//=============================================================================
int RXPPeerHandler::ConnectHandleError(int Error, char* Parameter)
{
	return RXP_HANDLER_FAILURE;
}

int RXPPeerHandler::ListenHandleError(int Error, char* Parameter)
{
	return RXP_HANDLER_FAILURE;
}

//=============================================================================
//	RXPPeerHandlerReliable
//=============================================================================

int RXPPeerHandlerReliable::ConnectHandleError(int Error, char* Parameter)
{
	return RXP_HANDLER_FAILURE;
}

int RXPPeerHandlerReliable::ListenHandleError(int Error, char* Parameter)
{
	int		Result	=	RXP_HANDLER_SUCCESS;

	if ( Error == WSAENETDOWN )
	{
		if ( Peer->GetListenAttempt() < 10 )
		{	Peer->RetryListenAfterAdditional(15000);
		} else 
		{	Peer->RetryListenAfterAdditional(0);
		}
	}
	else if ( Error == WSAEADDRINUSE )
	{
		// Todo: Ask the calling function whether it's OK to relocate the conenction to another port
		if ( Peer->GetListenAttempt() < 2 )
		{	Peer->RetryListenAfterAdditional(10000);
		} else 
		{	Peer->RetryListenAfterAdditional(0);
		}
	}
	else if ( Error == WSAEADDRNOTAVAIL )
	{
		if ( Peer->GetListenAttempt() < 3 )
		{	Peer->RetryListenAfterAdditional(100000);
		} else 
		{	Peer->RetryListenAfterAdditional(0);
		}
	}
	else if ( Error == WSAEMFILE )
	{
		if ( Peer->GetListenAttempt() < 5 )
		{	Peer->RetryListenAfterAdditional(5000);
		} else 
		{	Peer->RetryListenAfterAdditional(0);
		}
	}
	else if ( Error == WSAENOBUFS )
	{
		if ( Peer->GetListenAttempt() < 5 )
		{	Peer->RetryListenAfterAdditional(1000);
		} else 
		{	Peer->RetryListenAfterAdditional(0);
		}
	}
	else if ( Error == RXP_ERROR_ALLOC_FAIL )
	{
		// A required memory allocation failed!
		// Try again a little later, it might go away by itself, or the
		// user will take care and free some resources. Or perhaps get a new
		// computer with unheard amounts of RAM?
		if ( Peer->GetListenAttempt() < 25 )
		{	Peer->RetryListenAfterAdditional(200);
		} else
		{	Peer->RetryListenAfterAdditional(0);
		}
	}
	else
	{
		// Try a few times to fix unknown errors and then try after a long time.
		if ( Peer->GetListenAttempt() < 2 )
		{
			Peer->RetryListenAfterAdditional(1000);
		}
		else if ( Peer->GetListenAttempt() < 3 )
		{
			Peer->RetryListenAfterAdditional(60000);
		}
		else
		{
			Peer->RetryListenAfterAdditional(0);
		}
	}

	return Result;
}

//=============================================================================
//	RXPPeer
//=============================================================================

RXPPeer::RXPPeer()
{
	ListenPort				=	0;
	ListenSocket			=	INVALID_SOCKET;	
	AcceptingConnection		=	NULL;
	PeerHWND				=	NULL;
	Handler					=	NULL;
	ListenAttempt			=	0;
	ListenWait				=	0;
	ListenNextTime			=	ME_THINK_NEVER;
	ListeningState			=	RXP_LISTEN_DONT;

	// By default, don't listen reliably
	ListenReliably			=	false;

	// Initialize Winsock
	WSAState				=	WSAStartup(MAKEWORD(RXP_WINSOCK_REQUIRED_MAJOR, RXP_WINSOCK_REQUIRED_MINOR), &WSAData);
}

RXPPeer::~RXPPeer()
{
	DestroyPeer();

	if ( WSAInitialized() )
	{
		WSACleanup();
	}

	if ( Handler ) { delete[] Handler; }
}

bool RXPPeer::SetHandler(RXPPeerHandler* NewHandler)
{
	if ( !NewHandler ) { return false; }
	if ( Handler == NewHandler ) { return true; }

	if ( Handler )
	{
		delete Handler;
	}

	Handler			=	NewHandler;
	Handler->Peer	=	this;

	return true;
}

BOOL RXPPeer::InitializePeer(HINSTANCE hInstance)
{
	if ( RXPPeerClassRegistered == false )
	{
		WNDCLASSM  wc = {0};

		wc.lpfnWndProc = (WNDPROC) MaxsiRXPPeerProc;
		wc.hInstance = (HINSTANCE)hInstance;
		wc.hIcon = LoadIconA((HINSTANCE)hInstance, "ProductIcon");
		wc.hCursor = LoadCursor(NULL, IDC_ARROW);
		wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
		wc.lpszClassName = _MESTR("MaxsiRXPPeer");

		if ( RegisterClassM(&wc) == 0 )
		{
			int		Error	=	GetLastError();
			return FALSE;
		}

		RXPPeerClassRegistered	=	true;
	}

	if ( PeerHWND == NULL )
	{
		PeerHWND = CreateWindowM(
			_MESTR("MaxsiRXPPeer"),
			_MESTR("MaxsiRXPPeer"),
			0,
			0, 0,
			1, 1,
			NULL, NULL, hInstance, NULL );

		if ( PeerHWND == NULL )
		{
			int		Error	=	GetLastError();
			return FALSE;
		}
	}

	return TRUE;
}

BOOL	RXPPeer::DestroyPeer()
{
	if ( PeerHWND ) { DestroyWindow(PeerHWND); PeerHWND = NULL; }

	return TRUE;
}

bool	RXPPeer::WSAInitialized()
{
	return	(WSAState==0);
}

bool	RXPPeer::WSASupported()
{
	// Check whether Winsock can provide the version of Winsock we require
	return ( LOBYTE(WSAData.wVersion) == RXP_WINSOCK_REQUIRED_MAJOR &&
			 HIBYTE(WSAData.wVersion) == RXP_WINSOCK_REQUIRED_MINOR  );
}

bool	RXPPeer::WSAError()
{
	WSALastError	=	WSAGetLastError();

	MESTR*	Temporary;
	DWORD	Success		=	FormatMessageM(FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, WSALastError, LANG_NEUTRAL, (LPSTR)&Temporary, 0, NULL);

	if ( Success ) 
	{
		char*	ErrorMessage	=	BuildString(1,Temporary);
		LocalFree(Temporary);

		if ( ErrorMessage )
		{
			// Todo: Do something with WSALastError and ErrorMessage here.

			delete[] ErrorMessage;
		}
	}
	
	return (Success>0);
}

int RXPPeer::OnThink()
{
	if ( ListeningState == RXP_LISTEN_SHOULD )
	{
		DWORD	CurrentTime		=	GetTickCount();
		if ( ListenNextTime <= CurrentTime )
		{
			int	ListenResult;
			
			while ( (ListenResult = DoListen(ListenPort)) == RXP_LISTEN_AGAIN ) { }

			if ( ListenResult == RXP_LISTEN_FAIL &&
				 Handler &&
				 Handler->ListenHandleError(WSALastError) == RXP_HANDLER_FAILURE )
			{
				// Shut down here!
				int leet = 1337;
			}
		}
		else
		{
			RequestThinkBefore(ListenNextTime - CurrentTime, ME_THINK_PRECISION_LOW);
		}
	}
	
	return ME_THINK_SUCCESS;
}

int RXPPeer::ShutdownListen()
{
	if ( ListenSocket != INVALID_SOCKET ) { closesocket(ListenSocket); ListenSocket = INVALID_SOCKET; }
	return 1;
}

int	RXPPeer::Listen(short Port)
{
	EnterCriticalSection(&MayExecThinkFunction);

	ListenPort		=	Port;
	ListeningState	=	RXP_LISTEN_SHOULD;
	ListenNextTime	=	0;

	LeaveCriticalSection(&MayExecThinkFunction);

	Think();

	return RXP_LISTEN_SUCCESS;
}

int	RXPPeer::DoListen(short Port)
{
	if ( !WSASupported() ) { return RXP_LISTEN_FAIL; }

	if ( ListenSocket == INVALID_SOCKET )
	{
		if (INVALID_SOCKET == (ListenSocket = socket(AF_INET, SOCK_STREAM, 0)) )
		{
			WSAError();
			return RXP_LISTEN_FAIL;
		}

		SOCKADDR_IN addr;

		ListenPort				=	Port;

		addr.sin_family			=	AF_INET;
		addr.sin_addr.s_addr	=	INADDR_ANY;
		addr.sin_port			=	htons((short)Port);

		if ( 0 != bind(ListenSocket, (SOCKADDR *)&addr, sizeof(addr)) )
		{
			// Possible error values to handle:
			// - WSAEADDRINUSE
			// - WSAEADDRNOTAVAIL
			// - WSAENOBUFS
			WSAError();
			ShutdownListen();
			return RXP_LISTEN_FAIL;
		}

		if ( 0 != listen(ListenSocket, SOMAXCONN) )
		{
			// Possible error values to handle:
			// - WSAEADDRINUSE
			// - WSAENOBUFS
			WSAError();
			ShutdownListen();
			return RXP_LISTEN_FAIL;
		}

		if (0 == BindIoCompletionCallback((HANDLE)ListenSocket, RXPConnection__DoneIO, 0) )
		{
			ShutdownListen();
			return RXP_LISTEN_FAIL;
		}
	}

	if ( AcceptingConnection == NULL )
	{
		AcceptingConnection			=	new	RXPConnection*[RXP_CONCURRENT_LISTENS];

		if ( AcceptingConnection )
		{
			memset(AcceptingConnection,0,RXP_CONCURRENT_LISTENS*sizeof(RXPConnection*));
		}
	}

	if ( AcceptingConnection )
	{
		for ( size_t I = 0; I < RXP_CONCURRENT_LISTENS; I++ )
		{
			if ( AcceptingConnection[I] == NULL)
			{
				AcceptingConnection[I]		=	new	RXPConnection;
				if ( AcceptingConnection[I] )
				{
					AcceptingConnection[I]->Peer			=	this;
					AcceptingConnection[I]->ConnectionId	=	I;
				}
			}

			if ( AcceptingConnection[I] )
			{
				int ListenResult;
				while ( (ListenResult = AcceptingConnection[I]->Listen(Port)) == RXP_LISTEN_AGAIN ) { }
				
				if ( ListenResult == RXP_LISTEN_FAIL )
				{
					return RXP_LISTEN_FAIL;
				}
			}
			else
			{
				WSALastError	=	RXP_ERROR_ALLOC_FAIL;
				return RXP_LISTEN_FAIL;
			}
		}

		ListeningState	=	RXP_LISTEN_LISTENING;

		return RXP_LISTEN_SUCCESS;
	}
	else
	{
		WSALastError	=	RXP_ERROR_ALLOC_FAIL;
		return RXP_LISTEN_FAIL;
	}
}

size_t RXPPeer::GetListenAttempt()
{
	return ListenAttempt;
}

int RXPPeer::ListenSuccess()
{
	ListenAttempt	=	0;
	ListenWait		=	0;
	return RXP_LISTEN_SUCCESS;
}

int RXPPeer::RetryListenAfterAdditional(DWORD Miliseconds)
{
	ListenAttempt++;

	ListenWait		=	ListenWait+Miliseconds;
	ListenNextTime	=	GetTickCount() + ListenWait;

	RequestThinkBefore(ListenWait, ME_THINK_PRECISION_LOW);

	return RXP_LISTEN_SUCCESS;
}

//=============================================================================
//	RXPConnection
//=============================================================================

RXPConnection::RXPConnection()
{	
	Connected		=	RXP_UNCONNECTED;

	memset(&Input,0,sizeof(Input));
	memset(&Output,0,sizeof(Output));

	Input.Connection	=	this;
	Input.BufferType	=	RXP_INPUT;
	Output.Connection	=	this;
	Output.BufferType	=	RXP_OUTPUT;

	Socket				=	INVALID_SOCKET;

	IBuffer				=	NULL;
	OBuffer				=	NULL;

	HostName			=	NULL;

	Timer				=	NULL;
	LastRemoteActivity	=	0xFFFFFFFF;
	NextScheduledTime	=	0xFFFFFFFF;
	NextRequestedTime	=	0xFFFFFFFF;	

	IBitDepth			=	RXP_Default_Bit_Depth;
	OBitDepth			=	RXP_Default_Bit_Depth;

	DeleteMe_WriteOnce	=	true;
}

RXPConnection::~RXPConnection()
{	
	DeleteBuffers();
	if ( HostName ) { delete[] HostName; }
}

bool	RXPConnection::WSAError()
{
	if ( Peer ) { return Peer->WSAError(); }
	return false;
}

bool	RXPConnection::CreateBuffers()
{	
	if ( IBuffer ) { DeleteBuffer(IBuffer); }	IBuffer	=	CreateBuffer(RXP_OBuffer_Size);
	if ( OBuffer ) { DeleteBuffer(OBuffer); }	OBuffer	=	CreateBuffer(RXP_IBuffer_Size);

	return ( IBuffer && OBuffer );
}

bool	RXPConnection::DeleteBuffers()
{	
	if ( IBuffer ) { DeleteBuffer(IBuffer); IBuffer	=	NULL; }
	if ( OBuffer ) { DeleteBuffer(OBuffer); OBuffer	=	NULL; }

	return true;
}

bool	RXPConnection::Shutdown()
{
	if ( Socket != INVALID_SOCKET ) { closesocket(Socket); Socket = INVALID_SOCKET; }
	return true;
}

bool	RXPConnection::Connect(MESTR* Host, short Port)
{
#if 0
	if (Socket == INVALID_SOCKET)
	{
		Socket = socket(AF_INET, SOCK_STREAM, 0);
	}

	SOCKADDR_IN addr;

	addr.sin_family				=	AF_INET;

	addr.sin_port				=	htons((short)80); // HTTP
	char*	HostName			=	GetHostFromURI(Host);		
	addr.sin_addr.S_un.S_addr	=	HostToIp(HostName);
	delete[] HostName;

	if ( WSAAsyncSelect(Socket,Peer->WindowHWND,ME_TorrentMessageID,FD_CONNECT|FD_CLOSE) != 0 )
	{		
		int	Error	=	WSAGetLastError();

		return false;
	}

	if ( connect(Socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == 0 )
	{
		// With a nonblocking socket, the connection attempt cannot be completed
		// immediately. In this case, connect will return SOCKET_ERROR, and
		// WSAGetLastError will return WSAEWOULDBLOCK.
		ME_UNDEFINED_BEHAVIOR("Connect() returned 0 on a nonblocking socket, which shouldn't happen.");
	}
	else
	{
		if ( WSAGetLastError() == WSAEWOULDBLOCK )
		{
			// Success! (So far!)
		}
		else
		{
			ME_UNDEFINED_BEHAVIOR("connect() returned not-null and WSAGetLastError() wasn't WSAEWOULDBLOCK.");
		}
	}
#endif
	return true;
}

bool	RXPConnection::OnConnected()
{
	if (0 == BindIoCompletionCallback((HANDLE)Socket, RXPConnection__DoneIO, 0) )
	{
		return false;
	}

	IBuffer->Lock(ME_BUFFER_LOCK_PARAMS);
	IBuffer->ClearInUse();
	IBuffer->Unlock();
	OBuffer->Lock(ME_BUFFER_LOCK_PARAMS);
	OBuffer->ClearInUse();
	OBuffer->Unlock();

 	Think();

	return true;
}


int	RXPConnection::Listen(short Port)
{
	int	Result	=	RXP_LISTEN_FAIL;

	EnterCriticalSection(&MayExecThinkFunction);

	ListenPort	=	Port;

	// Create a listening socket!
	if (Socket == INVALID_SOCKET)
	{
		Socket = socket(AF_INET, SOCK_STREAM, 0);
	}

	if ( Socket != INVALID_SOCKET )
	{
		DWORD					Received; // Never set if we complete async!
		
		Connected			=	RXP_ACCEPTING; // Mark this connection as an accepter!
		Input.Peer			=	Peer;
		Output.Peer			=	Peer;

		memset(AddrBuffer, 0, RXP_ADDRBUFFER_LEN);

		if (!AcceptEx(Peer->ListenSocket,	
			Socket,
			AddrBuffer,
			0,
			sizeof(sockaddr_in) + 16,
			sizeof(sockaddr_in) + 16,
			&Received,
			&Input))
		{
			int	LastError	=	WSAGetLastError();

			if ( LastError == ERROR_IO_PENDING )
			{
				Result		=	RXP_LISTEN_SUCCESS;
			}
			else if ( LastError == WSAECONNRESET )
			{
				// Connection was terminated by remote peer prior to accepting
				// the call. Just listen again. I am not sure if this will ever
				// get called due to the async nature of completion ports --
				// But it's better to be safe, so this won't cause the listening
				// system to fail.
				Result		=	RXP_LISTEN_AGAIN;
			}
			else
			{
				WSAError();
				closesocket(Socket);
				Result	=	RXP_LISTEN_FAIL;
			}
		}
		else
		{
			// I am not sure if this is even possible, but if it is,
			// enter a non-stack-increasing loop
			if ( OnConnectionAccepted(true) == RXP_LISTEN_SUCCESS )
			{
				Result		=	RXP_LISTEN_AGAIN;
			}
			else
			{
				Result		=	RXP_LISTEN_FAIL;
			}
		}
	}
	else
	{
		// We failed to create a socket!
	}

	LeaveCriticalSection(&MayExecThinkFunction);

	return Result;
}

int	RXPConnection::OnConnectionAccepted(bool Sync)
{
	int locallen, remotelen;
	sockaddr_in *plocal = 0, *premote = 0;

	GetAcceptExSockaddrs(AddrBuffer,
		0,
		sizeof(sockaddr_in) + 16,
		sizeof(sockaddr_in) + 16,
		(sockaddr **)&plocal,
		&locallen,
		(sockaddr **)&premote,
		&remotelen);

	if ( HostName ) { delete[] HostName; }

	HostName						=	RXPAddressToString((sockaddr*)premote, remotelen);

	RXPConnection*	Accepter		=	new RXPConnection;

	if ( !Accepter ) { return RXP_LISTEN_FAIL; }

	Accepter->Socket				=	Socket;
	Accepter->Connector				=	false;
	Accepter->Connected				=	RXP_CONNECTED;
	Accepter->Peer					=	Peer;
	Accepter->ConnectionId			=	ConnectionId;
	Accepter->LastRemoteActivity	=	GetTickCount();

	bool	Result					=	Accepter->OnConnectee();

	if ( !Result ) { return RXP_LISTEN_FAIL; }

	// Mark when we last successfully had a connection!
	LastRemoteActivity				=	GetTickCount();

	Socket							=	INVALID_SOCKET;

	int ListenResult				=	RXP_LISTEN_SUCCESS;

	// Avoid stack overflows
	while ( Sync == false && (ListenResult = Listen(ListenPort)) == RXP_LISTEN_AGAIN ) { };

	return ListenResult;
}

bool	RXPConnection::OnConnectee()
{
	bool	Result	=	true;

	EnterCriticalSection(&MayExecThinkFunction);

	Input.Peer		=	Peer;
	Output.Peer		=	Peer;

	if (0 == BindIoCompletionCallback((HANDLE)Socket, RXPConnection__DoneIO, 0) )
	{
		Result		=	false;
	}

	// Initialize this connection as a connectee, bind the callback, create buffer, read, etc.!
	if ( Result ) { Result = (0 == BindIoCompletionCallback((HANDLE)Socket, RXPConnection__DoneIO, 0)); }

	if ( Result ) { Result = CreateBuffers(); }

	if ( Result ) {	Result = Read(0); }

	LeaveCriticalSection(&MayExecThinkFunction);

	return Result;
}


void	RXPConnection::DoneIO(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, RXPOVERLAPPED* lpOverlapped)
{
	if ( dwErrorCode == 0)
	{
		if ( Connected == RXP_ACCEPTING )
		{
			EnterCriticalSection(&MayExecThinkFunction);

			int	ListenResult;

			while ((ListenResult = OnConnectionAccepted()) == RXP_LISTEN_AGAIN) { }

			if ( ListenResult == RXP_LISTEN_FAIL )
			{
				Shutdown();
			}
				
			LeaveCriticalSection(&MayExecThinkFunction);
		}
		else
		{
			if ( dwNumberOfBytesTransferred != 0 )
			{
				if ( lpOverlapped == &Input )
				{	
					IBuffer->Lock(ME_BUFFER_LOCK_PARAMS);
					IBuffer->ClearInUse();
					IBuffer->SetBufferUsed(IBuffer->GetBufferUsed() + dwNumberOfBytesTransferred);
					IBuffer->Unlock();

					EnterCriticalSection(&MayExecThinkFunction);

					// We have received data! Ensure we don't timeout anytime soon!
					LastRemoteActivity	=	GetTickCount();
				
					LeaveCriticalSection(&MayExecThinkFunction);
				}
			}
		}
	}

	Think();

	return;
}

bool RXPConnection::Write(char* Buffer, size_t BufferLen)
{
	if (!OBuffer) { return false; }

	bool	Result	=	true;

	OBuffer->Lock(ME_BUFFER_LOCK_PARAMS);

	if ( OBuffer->IsInUse() == ME_ERROR_SUCCESS && OBuffer->MayWrite() == ME_ERROR_SUCCESS )
	{
		if ( BufferLen > OBuffer->GetBufferSize() )
		{
			ME_UNDEFINED_BEHAVIOR("RXPConnection::Write() attempted to write more data to the output buffer than it could handle!");

			Result	=	false;
		}
		else
		{
			OBuffer->Clear();
			OBuffer->Write(Buffer,BufferLen);
			OBuffer->SetInUse();

			if ( WriteFile((HANDLE)Socket,
				OBuffer->GetBuffer(),
				(DWORD)BufferLen,
				NULL,
				&Output) == FALSE )
			{
				DWORD nLastError = GetLastError();
				if (ERROR_IO_PENDING != nLastError)
				{
					ME_DONT_COMPILE_RELEASE_BUILD();
					// Is the following correct?


					MESTR*	WroteStr		=	UIToA(nLastError);	
					MESTR*	ErrorMSG		=	BuildString(3,"Write Failure #",WroteStr," in ME_ServerClient::Write() !");
					ME_UNDEFINED_BEHAVIOR(ErrorMSG);
					OBuffer->ClearInUse();
					Result	=	false;
					delete[] ErrorMSG;
					delete[] WroteStr;
				}
			}
		}
	}
	else
	{
		Result	=	false;
	}

	OBuffer->Unlock();

	return Result;
}

bool RXPConnection::Read(size_t Keep)
{
	if (!IBuffer) { return false; }

	bool	Result	=	true;

	IBuffer->Lock(ME_BUFFER_LOCK_PARAMS);

	if ( IBuffer->IsInUse() == false && IBuffer->MayWrite() == ME_ERROR_SUCCESS)
	{
		if ( Keep > IBuffer->GetBufferUsed() )
		{
			ME_UNDEFINED_BEHAVIOR("RXPConnection::Read() attempted to keep more data than was in the buffer.");

			Result	=	false;
		}
		else
		{
			if ( Keep == 0 )
			{
				// We don't have to keep the contents in the buffer, so reset the buffer pointer,
				// set the length of the used buffer to 0, and then overwrite the contents.
				IBuffer->Clear();
			}
			else
			{
				// Keep > 0, so keep the last Keep bytes in the buffer while requesting some more
				// It'd be easier if we simply moved the kept bytes to the start of the buffer,
				// but it saves precious CPU cycles to just leave them where they are and append
				// some data after their location - chance is the (perhaps) few bytes, there is currently
				// room for, is enough to continue the process this peer is doing.

				// If it's not, the peer will execute its think function but fail to parse the new data,
				// and then call us again. Perhaps there is room at the start of the buffer that we can
				// write to. If that isn't enough room to complete the process, then the buffer should
				// have been larger in the first place - or the calling client should have been programmed
				// differently.
			}

			if ( IBuffer->GetBufferSize() <= Keep )
			{
				ME_UNDEFINED_BEHAVIOR("RXPConnection::Read() attempted to keep the entire buffer (or more) - This means there is no space for new data!");
			}

			IBuffer->SetInUse();
			IBuffer->ProgressBuffer(IBuffer->GetBufferUsed()-Keep);

			size_t	dP	=	(IBuffer->GetBufferOffset() + IBuffer->GetBufferUsed() ) % IBuffer->GetBufferSize();
			size_t	dL	=	( dP < IBuffer->GetBufferOffset() ) ? IBuffer->GetBufferOffset()-dP : IBuffer->GetBufferSize()-dP;

			if ( ReadFile((HANDLE)Socket,
				IBuffer->GetBuffer()+dP,
				(DWORD)dL,
				NULL,
				&Input) == FALSE )
			{
				DWORD nLastError = GetLastError();

				// Values to handle:
				// - ERROR_HANDLE_EOF (FileSystem only)
				// - ERROR_INVALID_USER_BUFFER (May happen when there are too much I/O going on)
				// - ERROR_NOT_ENOUGH_MEMORY (May happen when there are too much I/O going on)
				// - ERROR_NOT_ENOUGH_QUOTA?

				if (ERROR_IO_PENDING != nLastError)
				{
					WSAError();
				}
			}
		}
	}
	else
	{
		Result	=	false;
	}

	IBuffer->Unlock();

	return Result;
}

int	RXPConnection::OnThink()
{
	if ( Connected == RXP_CONNECTED )
	{
		// Have we timed out?
		if ( LastRemoteActivity + RXP_Inactive_Connection_Timeout < GetTickCount() )
		{
			Shutdown();
		}
		else
		{
			IBuffer->Lock(ME_BUFFER_LOCK_PARAMS);

			size_t	OutputLen	=	IBuffer->GetBufferUsed();

			char*	Output		=	new char[OutputLen+1];

			IBuffer->Read(Output, OutputLen);

			Output[OutputLen] = 0;

			IBuffer->Clear();

			IBuffer->Unlock();

			if ( DeleteMe_WriteOnce )
			{
				char* Out = "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nContent-Length: 112\r\n\r\n<html><head><title>Test</title></head><body><h1>Yay! It works!!</h1><br />Rick roll here, please</body></html>";
				DeleteMe_WriteOnce	=	false;

				Write(Out, strlen(Out));
			}

			// Request a timeout!
			DWORD	ConnectionTimeOutIn		=	LastRemoteActivity + RXP_Inactive_Connection_Timeout
											-	GetTickCount();

			RequestThinkBefore(ConnectionTimeOutIn);
		}
	}

	return true;
}

//=============================================================================
//	Implementations of the callback functions
//=============================================================================

void CALLBACK RXPConnection__DoneIOWSA(DWORD dwErrorCode,
					 DWORD dwNumberOfBytesTransferred,
					 LPOVERLAPPED lpOverlapped,
					 DWORD dwFlags)
{
	return	RXPConnection__DoneIO(dwErrorCode,dwNumberOfBytesTransferred,lpOverlapped);
}

void CALLBACK RXPConnection__DoneIO(DWORD dwErrorCode,
					 DWORD dwNumberOfBytesTransferred,
					 LPOVERLAPPED lpOverlapped)
{
	RXPOVERLAPPED*	Ov		=	(RXPOVERLAPPED*)lpOverlapped;
	if (Ov->Connection)
	{
		Ov->Connection->DoneIO(dwErrorCode,dwNumberOfBytesTransferred,Ov);
	}
	return;
}

//=============================================================================
//	Implementations of the timer callback functions
//=============================================================================

void CALLBACK ME_Think_Timer_Callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
	if ( lpParameter != NULL )
	{
		ME_Thinker*	Thinker	=	(ME_Thinker*)lpParameter;

		EnterCriticalSection(&Thinker->MayExecThinkFunction);

		Thinker->NextRequestedTime	=	ME_THINK_NEVER;
		Thinker->Think();

		EnterCriticalSection(&Thinker->MayExecThinkFunction);
	}
}

//void CALLBACK RXPTimerCallback(PVOID lpParameter,
//					BOOLEAN TimerOrWaitFired)
//{
//	if ( lpParameter != NULL )
//	{
//		RXPConnection*	Connection	=	(RXPConnection*)lpParameter;
//		
//		EnterCriticalSection(&Connection->MayExecThinkFunction);
//
//		if ( Connection->Timer )
//		{
//			DeleteTimerQueueTimer(Connection->Peer->TimerQueue, Connection->Timer, NULL);
//			Connection->Timer = NULL;
//			Connection->NextRequestedTime	=	0xFFFFFFFF;
//		}
//		
//		Connection->Think();
//
//		LeaveCriticalSection(&Connection->MayExecThinkFunction);
//	}
//}
//
//void CALLBACK RXPListenCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
//{
//	if ( lpParameter != NULL )
//	{
//		RXPPeer*	Peer	=	(RXPPeer*)lpParameter;
//
//		if ( Peer->ListenTimer )
//		{
//			DeleteTimerQueueTimer(Peer->TimerQueue, Peer->ListenTimer, NULL);
//		}
//		
//		Peer->ReliableListen(Peer->ListenPort);
//	}
//}